package com.sailor.dingding.utils;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiMessageCorpconversationAsyncsendV2Request;
import com.dingtalk.api.request.OapiV2UserGetbymobileRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiMessageCorpconversationAsyncsendV2Response;
import com.dingtalk.api.response.OapiV2UserGetbymobileResponse;
import com.taobao.api.ApiException;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;

/**
 * @description: 钉钉发送消息工具类
 * @author: wwz
 * @date: 2023/02/03
 */
@Slf4j
public class DingdingSendMsgUtil {

    @Autowired
    private RedissonClient redissonClient;

    public static final Long REQUEST_SUCCESS = 0L;

    /**
     * token redis key
     */
    private static final String DINGDING_MSG_TOKEN = "dingding_msg_token";

    /**
     * 钉钉获取Token url
     */
    private static final String GET_TOKEN_URL = "https://oapi.dingtalk.com/gettoken";

    /**
     * 钉钉根据手机号获取UserId url
     */
    private static final String GET_USERID_URL = "https://oapi.dingtalk.com/topapi/v2/user/getbymobile";

    /**
     * 钉钉发送消息 url
     */
    private static final String SEND_WORK_MSG_URL = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2";

    /**
     * 钉钉消息通知
     *
     * @param content
     * @param phone
     * @param agentId
     * @param appKey
     * @param appSecret
     * @throws Exception
     */
    public void sendOAMsgByPhone(String content, String phone, String messageUrl,
                               Long agentId, String appKey, String appSecret) throws Exception {
        // 获取token
        RBucket<String> bucket = redissonClient.getBucket(DINGDING_MSG_TOKEN);
        String token = bucket.get();
        if (StringUtils.isBlank(token)) {
            token = getToken(appKey, appSecret, GET_TOKEN_URL);
            // 两小时过期时间
            bucket.set(token, 2, TimeUnit.HOURS);
            //redisTemplate.opsForValue().set(DINGDING_MSG_TOKEN,token,2,TimeUnit.HOURS);
        }
        // 根据手机号获取钉钉用户Id
        // 15531134484
        String dingUserId = getDingUserId(phone, token, GET_USERID_URL);
        try {
            // 发消息
            DingTalkClient client = new DefaultDingTalkClient(SEND_WORK_MSG_URL);
            OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
            request.setAgentId(agentId);
            request.setUseridList(dingUserId);
            request.setToAllUser(false);

            //request.setUseridList(StringUtils.join(dingdingIds, ","));
            OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
            msg.setOa(new OapiMessageCorpconversationAsyncsendV2Request.OA());
            msg.getOa().setHead(new OapiMessageCorpconversationAsyncsendV2Request.Head());
            msg.getOa().getHead().setText("head");
            msg.getOa().setBody(new OapiMessageCorpconversationAsyncsendV2Request.Body());
            msg.getOa().getBody().setContent(content);
            // 消息类型
            msg.setMsgtype("oa");
            // 手机端点击即可访问 PC端需要扫码
            msg.getOa().setMessageUrl(messageUrl);
            // PC端 跳转
            String pcUrl = URLEncoder.encode(messageUrl, StandardCharsets.UTF_8.name());
//              pc_slide true：表示在PC客户端侧边栏打开  false：表示在浏览器打开
            msg.getOa().setPcMessageUrl("dingtalk://dingtalkclient/page/link?url=" + pcUrl + "&pc_slide=false");
            // 设置OA 图片
            msg.getOa().getBody().setImage("@lAHPDe7s7xb3gxPNARjNARg");
            request.setMsg(msg);
            // 发图片消息
//            msg.setMsgtype("image");
//            msg.setImage(new OapiMessageCorpconversationAsyncsendV2Request.Image());
//            msg.getImage().setMediaId("@lAHPDe7s7xb3gxPNARjNARg");

            request.setMsg(msg);
            OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request, token);
            if (response.getErrcode() != REQUEST_SUCCESS) {
                log.error("SEND_DINGDING_MSG_ERROR(1 time),{},{}", response.getErrcode(), response.getErrmsg());
                // 重试一次
                response = client.execute(request, token);
                if (response.getErrcode() != REQUEST_SUCCESS) {
                    log.error("SEND_DINGDING_MSG_ERROR(2 time),{},{}", response.getErrcode(), response.getErrmsg());
                }
            }
        } catch (Exception e) {
            log.error("SEND_DINGDING_MSG_ERROR", e);
        }
    }

    /**
     * 获取钉钉 token
     *
     * @param appKey
     * @param appSecret
     * @param getTokenUrl
     * @return
     */
    public String getToken(String appKey, String appSecret, String getTokenUrl) {
        try {
            DingTalkClient client = new DefaultDingTalkClient(getTokenUrl);
            OapiGettokenRequest request = new OapiGettokenRequest();
            request.setAppkey(appKey);
            request.setAppsecret(appSecret);
            request.setHttpMethod("GET");
            OapiGettokenResponse response = client.execute(request);
            if (response.getErrcode() != REQUEST_SUCCESS) {
                log.error("get dingding token exception: {}, {}", response.getErrcode(), response.getErrmsg());
                response = client.execute(request);
                log.error("retry get dingding token : {}, {}", response.getErrcode(), response.getErrmsg());
            }
            return response.getAccessToken();
        } catch (Exception e) {
            log.error("get dingding token error", e);
        }
        return null;
    }

    /**
     * 根据手机号获取userId
     *
     * @param phone
     * @param token
     * @return
     */
    public String getDingUserId(String phone, String token, String getUserIdUrl) {
        try {
            DingTalkClient client = new DefaultDingTalkClient(getUserIdUrl);
            OapiV2UserGetbymobileRequest req = new OapiV2UserGetbymobileRequest();
            req.setMobile(phone);
            OapiV2UserGetbymobileResponse rsp = client.execute(req, token);
//          JacksonUtil.readValue(rsp.getBody().toString(),DingDingResponseVO.class);
            if (REQUEST_SUCCESS.equals(rsp.getErrcode())) {
                return rsp.getResult().getUserid();
            } else {
                throw new RuntimeException(rsp.getErrmsg());
            }
        } catch (ApiException e) {
            log.error("获取钉钉UserId 错误", e);
        }
        return null;
    }
}
